#include "window.h"
#include <vector>
#include <iostream>

#include "input.h"
#include "objectTreeItem.h"
#include "viewPanel.h"
#include "cuboidDialog.h"
#include "sphereDialog.h"
#include "cylinderDialog.h"
#include "coneDialog.h"
#include "operationDialog.h"
#include "analysisDialog.h"
#include "defines/primitive.h"
#include "defines/operation.h"
#include "src/combinedObject.h"

Window::Window(){
	setWindowTitle(QString::fromUtf8("[MODELAGEM GEOMÉTRICA] Octree"));
    statusBar()->showMessage(tr(""));
    setUnifiedTitleAndToolBarOnMac(true);

	canvas = new GLWidget(this);
	setCentralWidget(canvas);


	tree = NULL;

	inOperation = false;
	staticOctree = false;

	createWindow();
}

Window::~Window(){
	if(canvas) delete canvas;
    if(operationToolBar) delete operationToolBar;
    if(editObjectAct) delete editObjectAct;
    if(deleteObjectAct) delete deleteObjectAct;
    if(octreeToolBar) delete octreeToolBar;
    if(tree) delete tree;
}

void Window::changeSelection(){

//    std::cout <<"------Estaria mudando! seleção!" <<std::endl;
    if(inOperation) return;

    if(!objectsToolBar->isEnabled()){
        previousSelected = tree->selectedItems();
    }else{

//    std::cout <<"\t\tAntes de mudar!" <<std::endl;

        for(int i = 0; i < previousSelected.size(); i++){
            QTreeWidgetItem *item = previousSelected.at(i);
            ((ObjectTreeItem *)item)->select(false);
        }
        previousSelected.clear();

        QList<QTreeWidgetItem *> selected = tree->selectedItems();

        for(int i = 0; i < selected.size(); i++){
            QTreeWidgetItem *item = selected.at(i);
            ((ObjectTreeItem *)item)->select(true);
            previousSelected.push_back(item);
        }
        operationToolBar->setEnabled(selected.size() > 1);
        editObjectAct->setEnabled(selected.size() > 0);
        deleteObjectAct->setEnabled(selected.size() > 0);

    //    std::cout <<"\t\tMudou!" <<std::endl;
        canvas->updateGL();
    }
}

void Window::newScene(){
    staticOctree = false;
    emit onlyOctreeMode(staticOctree);
    updateActions();
    tree->clear();
    canvas->newScene();
    octreePushButton->setChecked(false);
}

int Window::addTreeItem(Object *_obj, QTreeWidgetItem *_item, bool _setId){
    if(_setId){
        _obj->setId(canvas->getScene()->nextObjectsID());
    }

    QTreeWidgetItem *newItem = new ObjectTreeItem(_item, _obj);

    if(!_obj->isPrimitive()){
        int currentMaxId, maxId = -1;
        for(unsigned int i = 0; i < ((CombinedObject *)_obj)->getObjectsSize(); i++){
            currentMaxId = addTreeItem(((CombinedObject *)_obj)->getObject(i), newItem, _setId);
            if(currentMaxId > maxId) maxId = currentMaxId;
        }
        return maxId;
    }else return _obj->getId();
}

int Window::updateObjects(std::vector<Object *> _objs){
    inOperation = true;
    QTreeWidgetItem *rootItem = tree->invisibleRootItem();

    bool setId = (canvas->getScene()->getObjectsSize() > 0);

    int currentMaxId, maxId = -1;
    for(unsigned int i = 0; i < _objs.size(); i++){
        Object *obj = _objs.at(i);
        canvas->getScene()->addObject(obj);

        currentMaxId = addTreeItem(obj, rootItem, setId);
        if(currentMaxId > maxId) maxId = currentMaxId;
    }

    inOperation = false;
    return maxId;
}

void Window::openObjects(){ 	QString filename = QFileDialog::getOpenFileName(this, tr("Acrescentar objetos"), QDir::currentPath(),tr("Arquivo de cenas (*.obs)"));

    if (!filename.isNull()){
//        qDebug() << "abrindo: " << filename;
        QFile* file = new QFile(filename);

        Input input;
        int maxId = updateObjects(input.parseObjects(file));
        canvas->getScene()->setNextObjectsID(maxId);

        output.setFile(file);
	}
	updateActions();
//	updateTreesVolume(false);
}

void Window::openSceneObjects(){
    newScene();

    std::cout <<"Podia perguntar se a pessoa quer salvar o ultimo ou não" <<std::endl;

	QString filename = QFileDialog::getOpenFileName(this, tr("Abrir cena"), QDir::currentPath(),tr("Arquivo de cenas (*.obs)"));

    if (!filename.isNull()){
        qDebug() << "abrindo: " << filename;
        QFile* file = new QFile(filename);

        Input input;
        int maxId = updateObjects(input.parseObjects(file));
        canvas->getScene()->setNextObjectsID(maxId);

        output.setFile(file);
	}
	updateActions();
//	updateTreesVolume(false);

}

void Window::updateOctrees(std::vector<Octree *> _octrees){
    staticOctree = true;
    canvas->getScene()->setOctrees(_octrees);

    QTreeWidgetItem *rootItem = tree->invisibleRootItem();

    for(unsigned int i = 0; i < _octrees.size(); i++){
        QString str = "Octree ";
        str.append(QString::number(i));
        QTreeWidgetItem *item = new QTreeWidgetItem(rootItem);
        item->setText(0, str);
    }

    emit onlyOctreeMode(staticOctree);
}

void Window::openSceneOctrees(){
    newScene();

    std::cout <<"Podia perguntar se a pessoa quer salvar o ultimo ou não" <<std::endl;

	QString filename = QFileDialog::getOpenFileName(this, tr("Abrir octrees"), QDir::currentPath(),tr("Arquivo de octrees (*.ocs)"));

    if (!filename.isNull()){
        qDebug() << "abrindo: " << filename;
        QFile* file = new QFile(filename);

        Input input;
        updateOctrees(input.parseOctrees(file));
	}
	updateActions();

}

void Window::saveSceneObjects(){
    if(output.isFileNull()) saveSceneObjectsAs();

    output.parseObjects(canvas->getScene());

    saveObjectsAct->setEnabled(false);
}

void Window::saveSceneObjectsAs(){
	QString filename = QFileDialog::getSaveFileName(this, tr("Salvar objetos da cena como..."), QDir::currentPath(), tr("Arquivo de objetos (*.obs)"));

    if (filename.isNull()) return;

    if (QFileInfo(filename).suffix().isEmpty())
        filename += ".obs";

    QFile* file = new QFile(filename);

	output.parseObjects(file, canvas->getScene());

    saveObjectsAct->setEnabled(false);
}

void Window::saveSceneOctrees(){
	QString filename = QFileDialog::getSaveFileName(this, tr("Salvar octrees da cena"), QDir::currentPath(), tr("Arquivo de octrees (*.ocs)"));

    if (filename.isNull()) return;

    if (QFileInfo(filename).suffix().isEmpty())
        filename += ".ocs";

    QFile* file = new QFile(filename);

	output.parseOctrees(file, canvas->getScene());

	saveOctreesAct->setEnabled(false);
}

void Window::rotateOctree(Object *_obj, int _rX, int _rY, int _rZ){
    inOperation = true;
    if(!octreePushButton->isChecked()){
        canvas->updateGL();
        inOperation = false;
        return;
    }
    Octree *octree = canvas->getScene()->getOctree(_obj);
    octree->rotate(_rX, _rY, _rZ);
}

void Window::redoOctree(Object *_obj){
    inOperation = true;
    if(!octreePushButton->isChecked()){
        canvas->updateGL();
        inOperation = false;
        return;
    }
    canvas->getScene()->addOctreeOf(_obj);
    canvas->updateGL();
    updateActions();

    inOperation = false;
}

void Window::redoOctree(std::vector<Object *> _objs){
    for(unsigned int i = 0; i < _objs.size(); i++){
        redoOctree(_objs.at(i));
    }

}

void Window::editObjectDialog(QTreeWidgetItem * _item, int){

    if(!objectsToolBar->isEnabled()) return;

    _item->setSelected(false);
    inOperation = true;

    Object *obj = ((ObjectTreeItem *)_item)->getObject();
    if(obj->isPrimitive()){
        switch(obj->getType()){
            case CUBOID:{
                CuboidDialog *dlg = new CuboidDialog((CuboidPrimitive *)obj, (ObjectTreeItem *)_item, this);
                dlg->show();

                connect(dlg, SIGNAL(redoOctree(Object *)), this, SLOT(redoOctree(Object *)));
                connect(dlg, SIGNAL(rotateOctree(Object *, int, int, int)), this, SLOT(rotateOctree(Object *, int, int, int)));
                break;
            }
            case SPHERE:{
                SphereDialog *dlg = new SphereDialog((SpherePrimitive *)obj, (ObjectTreeItem *)_item, this);
                dlg->show();

                connect(dlg, SIGNAL(redoOctree(Object *)), this, SLOT(redoOctree(Object *)));
                connect(dlg, SIGNAL(rotateOctree(Object *, int, int, int)), this, SLOT(rotateOctree(Object *, int, int, int)));
                break;
            }
            case CYLINDER:{
                CylinderDialog *dlg = new CylinderDialog((CylinderPrimitive *)obj, (ObjectTreeItem *)_item, this);
                dlg->show();

                connect(dlg, SIGNAL(redoOctree(Object *)), this, SLOT(redoOctree(Object *)));
                connect(dlg, SIGNAL(rotateOctree(Object *, int, int, int)), this, SLOT(rotateOctree(Object *, int, int, int)));
                break;
            }
            case CONE:{
                ConeDialog *dlg = new ConeDialog((ConePrimitive *)obj, (ObjectTreeItem *)_item, this);
                dlg->show();

                connect(dlg, SIGNAL(redoOctree(Object *)), this, SLOT(redoOctree(Object *)));
                connect(dlg, SIGNAL(rotateOctree(Object *, int, int, int)), this, SLOT(rotateOctree(Object *, int, int, int)));
                break;
            }
        }
    }
    else{
        OperationDialog *dlg = new OperationDialog((CombinedObject *)obj, (ObjectTreeItem *)_item, tree->invisibleRootItem(), canvas->getScene(), this);
        dlg->show();

        connect(dlg, SIGNAL(redoOctree(std::vector<Object *>)), this, SLOT(redoOctree(std::vector<Object *>)));
        connect(dlg, SIGNAL(rotateOctree(Object *, int, int, int)), this, SLOT(rotateOctree(Object *, int, int, int)));
    }

    updateActions();

    inOperation = false;
}

void Window::analyzeObject(){
    if(previousSelected.size() != 1) std::cout <<"Analisando numero de objetos errado" <<std::endl;

//    std::cout <<"Analisando objeto ";
    Object *obj = NULL;
    Octree *octree = NULL;

    if(!objectsToolBar->isEnabled()){
        QTreeWidgetItem *rootItem = tree->invisibleRootItem();
        for(int i = 0; i < rootItem->childCount(); i++){
            if(rootItem->child(i) == previousSelected.front()){
                octree = canvas->getScene()->getOctree(i);
                break;
            }
        }
    }else{

        obj = ((ObjectTreeItem *)previousSelected.front())->getObject();
//        std::cout <<obj->getId() <<std::endl;
        octree = NULL;
        if(octreePushButton->isChecked()) octree = canvas->getScene()->getOctree(obj);
    }
//    std::cout <<"antes"<<std::endl;
    AnalysisDialog *dlg = new AnalysisDialog(obj, octree, this);
    dlg->show();
//    std::cout <<"depois"<<std::endl;
}

void Window::deleteObject(){
    inOperation = true;
    for(int i = 0; i < previousSelected.size(); i++){
        QTreeWidgetItem *item = previousSelected.at(i);
        Object *obj = ((ObjectTreeItem *)item)->getObject();

        /*se o pai desse objeto não for o root,
        significa que ele eh uma composição,
        então tem que deletar esse objeto la também*/

        QTreeWidgetItem *parent = item->parent();
        if(parent == NULL){
            canvas->getScene()->deleteObject(obj);
            tree->invisibleRootItem()->removeChild(item);
        }
        else{
            Object *parentObj = (CombinedObject *)((ObjectTreeItem *)parent)->getObject();
            ((CombinedObject *)parentObj)->deleteObject(obj);
            parent->removeChild(item);

            if(parent->childCount() == 1){
                QTreeWidgetItem *otherItem = parent->child(0);
                parent->removeChild(otherItem);
                Object *otherItemObj = ((ObjectTreeItem *)otherItem)->getObject();

                QTreeWidgetItem *grandParent = parent->parent();
                if(grandParent == NULL){ //coloca na cena o objeto e na arvore principal
                    tree->invisibleRootItem()->addChild(otherItem);
                    canvas->getScene()->addObject(otherItemObj);

                    tree->invisibleRootItem()->removeChild(parent);
                    canvas->getScene()->deleteObject(parentObj);

                    redoOctree(otherItemObj);
                }else{
                    Object *grandParentObject = ((CombinedObject *)((ObjectTreeItem *)grandParent)->getObject());

                    grandParent->addChild(otherItem);
                    ((CombinedObject *)grandParentObject)->addObject(otherItemObj);

                    grandParent->removeChild(parent);
                    ((CombinedObject *)grandParentObject)->deleteObject(parentObj);

                    //atualiznado o pai mais acima
                    while(grandParent->parent() != NULL){
                        grandParent = grandParent->parent();
                    }
                    redoOctree(((CombinedObject *)((ObjectTreeItem *)grandParent)->getObject()));

                }


                delete parent;
                delete parentObj;
            }else{
                redoOctree(parentObj);
            }
        }

        delete item;
        delete obj;


    }
    updateActions();

    canvas->updateGL();

    previousSelected.clear();
    inOperation = false;
}

void Window::addPrimitive(Object *_obj){

    inOperation = true;
    QTreeWidgetItem *rootItem = tree->invisibleRootItem();

    canvas->getScene()->addObject(_obj);
    /*QTreeWidgetItem *newCuboidItem = */new ObjectTreeItem(rootItem, _obj);
    redoOctree(_obj);

    updateActions();

    inOperation = false;
}

void Window::newCuboidPrimitiveDialog(){
    CuboidDialog *dlg = new CuboidDialog(canvas->getScene()->nextObjectsID(), this);
    dlg->show();

    connect(dlg, SIGNAL(done(Object *)), this, SLOT(addPrimitive(Object *)));
}

void Window::newSpherePrimitiveDialog(){
    SphereDialog *dlg = new SphereDialog(canvas->getScene()->nextObjectsID(), this);
    dlg->show();

    connect(dlg, SIGNAL(done(Object *)), this, SLOT(addPrimitive(Object *)));
}

void Window::newCylinderPrimitiveDialog(){
    CylinderDialog *dlg = new CylinderDialog(canvas->getScene()->nextObjectsID(), this);
    dlg->show();

    connect(dlg, SIGNAL(done(Object *)), this, SLOT(addPrimitive(Object *)));
}

void Window::newConePrimitiveDialog(){
    ConeDialog *dlg = new ConeDialog(canvas->getScene()->nextObjectsID(), this);
    dlg->show();

    connect(dlg, SIGNAL(done(Object *)), this, SLOT(addPrimitive(Object *)));
}

std::vector<Object *> Window::preOperation(QTreeWidgetItem **parent){
    inOperation = true;


    *parent = previousSelected.at(0)->parent();
    std::vector<Object *> objects;
    objects.push_back(((ObjectTreeItem *)previousSelected.at(0))->getObject());

    for(int i = 1; i < previousSelected.size(); i++){
        QTreeWidgetItem *item = previousSelected.at(i);
        objects.push_back(((ObjectTreeItem *)item)->getObject());
        if(item->parent() != *parent) {
            inOperation = false;
            QMessageBox::information(this, QString::fromUtf8("Erro na operação"), QString::fromUtf8("Escolha objetos com o mesmo pai."));
            objects.clear();
            break;
        }
    }
    if(*parent){
        if((*parent)->childCount() == previousSelected.size()){
            inOperation = false;
            QMessageBox::information(this, QString::fromUtf8("Erro na operação"), QString::fromUtf8("Não se pode fazer uma operação com todos os filhos."));
            objects.clear();
        }
    }
    return objects;
}

void Window::postOperation(QTreeWidgetItem *_parent, Object *_obj){
    Object *parentObject = NULL;
    if(_parent == NULL){
        _parent = tree->invisibleRootItem();
        canvas->getScene()->addObject(_obj);
    }else{
        parentObject = ((ObjectTreeItem *)_parent)->getObject();
        ((CombinedObject *)parentObject)->addObject(_obj);
    }
    QTreeWidgetItem *newCombinedItem = new ObjectTreeItem(_parent, _obj);


    int size = previousSelected.size();
    for(int i = 0; i < size; i++){
        QTreeWidgetItem *item = previousSelected.at(i);
        Object *currentObj = ((ObjectTreeItem *)item)->getObject();
        currentObj->select(false);
        if(!parentObject){
            canvas->getScene()->deleteObject(currentObj);
        }else{
            ((CombinedObject *)parentObject)->deleteObject(currentObj);
        }


        _parent->removeChild(item);
        newCombinedItem->addChild(item);
        item->setExpanded(true);
    }
    //se ctree esta ativa, recalcular para o objeto aou para o pai mais distante

    if(_parent == tree->invisibleRootItem()){
        redoOctree(_obj);
    }else{
        while(_parent->parent() != NULL){
            _parent = _parent->parent();
        }
        redoOctree(((ObjectTreeItem *)_parent)->getObject());

    }


    previousSelected.clear();
    updateActions();
    inOperation = false;
}

void Window::unionOperation(){
    QTreeWidgetItem *parent;
    std::vector<Object *> objects = preOperation(&parent);
    if(objects.empty()) return;

    postOperation(parent, new CombinedObject(UNION, objects, objects.at(0)->getColor(), canvas->getScene()->nextObjectsID()));
}

void Window::intersectionOperation(){
    QTreeWidgetItem *parent;
    std::vector<Object *> objects = preOperation(&parent);
    if(objects.empty()) return;

    postOperation(parent, new CombinedObject(INTERSECTION, objects, objects.at(0)->getColor(), canvas->getScene()->nextObjectsID()));
}

void Window::differenceOperation(){
    QTreeWidgetItem *parent;
    std::vector<Object *> objects = preOperation(&parent);
    if(objects.empty()) return;

    postOperation(parent, new CombinedObject(DIFFERENCE, objects, objects.at(0)->getColor(), canvas->getScene()->nextObjectsID()));
}

void Window::createWindow(){

    //Criando paineis ----------------------------------------------------------
    QDockWidget *treePanelDock = new QDockWidget(tr("Painel de objetos"), this);

    tree = new QTreeWidget(treePanelDock);
//    tree->setHeaderHidden(true);
    tree->setContextMenuPolicy(Qt::ActionsContextMenu);
    tree->setSelectionMode(QAbstractItemView::ExtendedSelection);
    tree->setSelectionBehavior(QAbstractItemView::SelectRows);
    tree->setAnimated(true);
    tree->setExpandsOnDoubleClick(false);



	treePanelDock->setWidget(tree);
    treePanelDock->setMaximumWidth(300);
//    treePanelDock->setMinimumHeight(200);
    addDockWidget(Qt::RightDockWidgetArea, treePanelDock);

    QTreeWidgetItem *headerItem = tree->headerItem();
    headerItem->setText(0, "Objetos");

    connect(tree, SIGNAL(itemSelectionChanged()), this, SLOT(changeSelection()));




    QDockWidget *viewPanelDock = new QDockWidget(QString::fromUtf8("Painel de visualização"), this);

    ViewPanel *viewPanel = new ViewPanel(viewPanelDock);

	viewPanelDock->setWidget(viewPanel);
    viewPanelDock->setMaximumWidth(300);
    viewPanelDock->setMaximumHeight(250);

    addDockWidget(Qt::RightDockWidgetArea, viewPanelDock);

    connect(viewPanel, SIGNAL(objectViewTypeChanged(unsigned int)), canvas, SLOT(changeObjectView(unsigned int)));
    connect(viewPanel, SIGNAL(octreeViewTypeChanged(unsigned int)), canvas, SLOT(changeOctreeView(unsigned int)));
    connect(this, SIGNAL(onlyOctreeMode(bool)), viewPanel, SLOT(onlyOctreeMode(bool)));




    //Criando ações ------------------------------------------------------------
    QAction *newSceneAct = new QAction(QString::fromUtf8("Nova Cena"), this);
    newSceneAct->setShortcuts(QKeySequence::New);
    newSceneAct->setStatusTip(QString::fromUtf8("Criar uma nava cena sem objetos."));
    connect(newSceneAct, SIGNAL(triggered()), this, SLOT(newScene()));

    QAction *openSceneObjectsAct = new QAction(QString::fromUtf8("Abrir cena"), this);
    openSceneObjectsAct->setShortcuts(QKeySequence::Open);
    openSceneObjectsAct->setStatusTip(QString::fromUtf8("Abrir uma nava cena de objetos."));
    connect(openSceneObjectsAct, SIGNAL(triggered()), this, SLOT(openSceneObjects()));

    openObjectsAct = new QAction(QString::fromUtf8("Abrir objetos"), this);
    openObjectsAct->setStatusTip(QString::fromUtf8("Abrir objetos na cena atual."));
    connect(openObjectsAct, SIGNAL(triggered()), this, SLOT(openObjects()));

    QAction *openSceneOctreesAct = new QAction(QString::fromUtf8("Abrir octrees"), this);
    openSceneOctreesAct->setStatusTip(QString::fromUtf8("Abrir octrees."));
    connect(openSceneOctreesAct, SIGNAL(triggered()), this, SLOT(openSceneOctrees()));

    saveObjectsAct = new QAction(QString::fromUtf8("Salvar objetos"), this);
    saveObjectsAct->setShortcuts(QKeySequence::Save);
    saveObjectsAct->setStatusTip(QString::fromUtf8("Salvar objetos da cena atual."));
    saveObjectsAct->setEnabled(false);
    connect(saveObjectsAct, SIGNAL(triggered()), this, SLOT(saveSceneObjects()));

    saveObjectsAsAct = new QAction(QString::fromUtf8("Salvar objetos como..."), this);
    saveObjectsAsAct->setShortcuts(QKeySequence::SaveAs);
    saveObjectsAsAct->setStatusTip(QString::fromUtf8("Salvar objetos da cena atual em novo arquivo."));
    connect(saveObjectsAsAct, SIGNAL(triggered()), this, SLOT(saveSceneObjectsAs()));

    saveOctreesAct = new QAction(QString::fromUtf8("Salvar octrees"), this);
    saveOctreesAct->setStatusTip(QString::fromUtf8("Salvar octrees da cena atual."));
    saveOctreesAct->setEnabled(false);
    connect(saveOctreesAct, SIGNAL(triggered()), this, SLOT(saveSceneOctrees()));

    QAction *exitAct = new QAction(QString::fromUtf8("Sair"), this);
    exitAct->setShortcuts(QKeySequence::Quit);
    exitAct->setStatusTip(QString::fromUtf8("Sair da aplicação."));
    connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));

    QAction *showAxisAct = new QAction(QString::fromUtf8("Eixos"), this);
    showAxisAct->setCheckable(true);
    showAxisAct->setChecked(canvas->isShowingAxis());
//    showAxisAct->setShortcuts();
    showAxisAct->setStatusTip(QString::fromUtf8("Mostrar eixos."));
    connect(showAxisAct, SIGNAL(toggled(bool)), canvas, SLOT(changeShowAxis(bool)));

    QAction *showGridAct = new QAction(QString::fromUtf8("Grade"), this);
    showGridAct->setCheckable(true);
    showGridAct->setChecked(canvas->isShowingGrid());
//    showGridAct->setShortcuts();
    showGridAct->setStatusTip(QString::fromUtf8("Mostrar grade."));
    connect(showGridAct, SIGNAL(toggled(bool)), canvas, SLOT(changeShowGrid(bool)));

	QAction *viewTreePanelAct = treePanelDock->toggleViewAction();

	QAction *viewPanelAct = viewPanelDock->toggleViewAction();

    editObjectAct = new QAction(QString::fromUtf8("Modificar objeto"), this);
    editObjectAct->setStatusTip(QString::fromUtf8("Modifica os objetos selecionados"));
    editObjectAct->setDisabled(true);
//    connect(editObjectAct, SIGNAL(triggered()), this, SLOT(editObjectDialog()));
    connect(tree, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(editObjectDialog(QTreeWidgetItem *, int)));



    deleteObjectAct = new QAction(QString::fromUtf8("Remover objetos"), this);
    deleteObjectAct->setStatusTip(QString::fromUtf8("Remove os objetos selecionados"));
    deleteObjectAct->setDisabled(true);
    connect(deleteObjectAct, SIGNAL(triggered()), this, SLOT(deleteObject()));

    analysisObjectAct = new QAction(QString::fromUtf8("Analisar objeto"), this);
    analysisObjectAct->setStatusTip(QString::fromUtf8("Analisar o objeto selecionado"));
    analysisObjectAct->setDisabled(true);
    connect(analysisObjectAct, SIGNAL(triggered()), this, SLOT(analyzeObject()));


    QAction *newCuboidAct = new QAction(QIcon("../bitmaps/cuboid.xpm"), QString::fromUtf8("Novo hexaedro"), this);
    newCuboidAct->setStatusTip(QString::fromUtf8("Cria um novo hexaedro, definido pelo seu ponto mínimo e máximo."));
    connect(newCuboidAct, SIGNAL(triggered()), this, SLOT(newCuboidPrimitiveDialog()));

    QAction *newSphereAct = new QAction(QIcon("../bitmaps/sphere.xpm"), QString::fromUtf8("Nova esfera"), this);
    newSphereAct->setStatusTip(QString::fromUtf8("Cria uma nova esfera, definida pelo centro e raio."));
    connect(newSphereAct, SIGNAL(triggered()), this, SLOT(newSpherePrimitiveDialog()));

    QAction *newCylinderAct = new QAction(QIcon("../bitmaps/cylinder.xpm"), QString::fromUtf8("Novo cilindro"), this);
    newCylinderAct->setStatusTip(QString::fromUtf8("Cria um novo cilindro, definido pelo centro, raio e altura."));
    connect(newCylinderAct, SIGNAL(triggered()), this, SLOT(newCylinderPrimitiveDialog()));

    QAction *newConeAct = new QAction(QIcon("../bitmaps/cone.xpm"), QString::fromUtf8("Novo cone"), this);
    newConeAct->setStatusTip(QString::fromUtf8("Cria um novo cone, definido pelo centro, raio e altura."));
    connect(newConeAct, SIGNAL(triggered()), this, SLOT(newConePrimitiveDialog()));

    QAction *unionAct = new QAction(QIcon("../bitmaps/union.xpm"), QString::fromUtf8("União"), this);
    unionAct->setStatusTip(QString::fromUtf8("Cria um objeto sendo a união de todos os selecionados."));
    connect(unionAct, SIGNAL(triggered()), this, SLOT(unionOperation()));

    QAction *intersectionAct = new QAction(QIcon("../bitmaps/intersection.xpm"), QString::fromUtf8("Interseção"), this);
    intersectionAct->setStatusTip(QString::fromUtf8("Cria um objeto sendo a interseção de todos os selecionados."));
    connect(intersectionAct, SIGNAL(triggered()), this, SLOT(intersectionOperation()));

    QAction *differenceAct = new QAction(QIcon("../bitmaps/difference.xpm"), QString::fromUtf8("Diferença"), this);
    differenceAct->setStatusTip(QString::fromUtf8("Cria um objeto sendo a diferença de todos os selecionados."));
    connect(differenceAct, SIGNAL(triggered()), this, SLOT(differenceOperation()));



    //Criando toolbar ----------------------------------------------------------
    objectsToolBar = addToolBar(tr("Barra de primitivas"));
    objectsToolBar->addAction(newCuboidAct);
    objectsToolBar->addAction(newSphereAct);
    objectsToolBar->addAction(newCylinderAct);
    objectsToolBar->addAction(newConeAct);

    operationToolBar = addToolBar(QString::fromUtf8("Barra de operações"));
    operationToolBar->addAction(unionAct);
    operationToolBar->addAction(intersectionAct);
    operationToolBar->addAction(differenceAct);
    operationToolBar->setDisabled(true);

    octreePushButton = new QPushButton(tr("Octree"));
    octreePushButton->setCheckable(true);
    octreePushButton->setChecked(false);
    connect(octreePushButton, SIGNAL(toggled(bool)), viewPanel, SLOT(enableOctree(bool)));
    connect(octreePushButton, SIGNAL(toggled(bool)), canvas, SLOT(octree(bool)));
//    connect(octreePushButton, SIGNAL(toggled(bool)), this, SLOT(updateTreesVolume(bool)));

    QLabel *octreeDepthLabel = new QLabel(QString("Profundidade: "));
    QSpinBox *octreeDepth = new QSpinBox;
    octreeDepth->setMinimum(1);
    octreeDepth->setMaximum(20);
    octreeDepth->setValue(3);
    connect(octreeDepth, SIGNAL(valueChanged(int)), canvas, SLOT(changeDepth(int)));


    connect(octreePushButton, SIGNAL(toggled(bool)), octreeDepthLabel, SLOT(setDisabled(bool)));
    connect(octreePushButton, SIGNAL(toggled(bool)), octreeDepth, SLOT(setDisabled(bool)));
    connect(octreePushButton, SIGNAL(toggled(bool)), this, SLOT(updateActions()));


    octreeToolBar = addToolBar(tr("Barra da octree"));
    octreeToolBar->addWidget(octreeDepthLabel);
    octreeToolBar->addWidget(octreeDepth);
    octreeToolBar->addWidget(octreePushButton);
    octreeToolBar->setDisabled(true);

	QAction *veiwObjectsToolBarAct = objectsToolBar->toggleViewAction();
	QAction *veiwOperationToolBarAct = operationToolBar->toggleViewAction();
	QAction *veiwOctreeToolBarAct = octreeToolBar->toggleViewAction();



    tree->addAction(analysisObjectAct);
    tree->addAction(deleteObjectAct);



    //Criando menus ------------------------------------------------------------
    QMenu *fileMenu;
    QMenu *editMenu;
    QMenu *viewMenu;

    fileMenu = menuBar()->addMenu(QString::fromUtf8("&Arquivo"));
    fileMenu->addAction(newSceneAct);
    fileMenu->addSeparator();
    fileMenu->addAction(openObjectsAct);
    fileMenu->addAction(openSceneObjectsAct);
    fileMenu->addSeparator();
    fileMenu->addAction(saveObjectsAct);
    fileMenu->addAction(saveObjectsAsAct);
    fileMenu->addSeparator();
    fileMenu->addAction(openSceneOctreesAct);
    fileMenu->addAction(saveOctreesAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);

    viewMenu = menuBar()->addMenu(QString::fromUtf8("&Visualizar"));
    viewMenu->addAction(showAxisAct);
    viewMenu->addAction(showGridAct);
//    viewMenu->addAction(wireframeObjectAct);
//    viewMenu->addAction(wireframeOctreeAct);
    viewMenu->addSeparator();
    viewMenu->addAction(viewTreePanelAct);
    viewMenu->addAction(viewPanelAct);
    viewMenu->addSeparator();
    viewMenu->addAction(veiwObjectsToolBarAct);
    viewMenu->addAction(veiwOperationToolBarAct);
    viewMenu->addAction(veiwOctreeToolBarAct);



    editMenu = menuBar()->addMenu(QString::fromUtf8("&Editar"));
    editMenu->addAction(editObjectAct);
    editMenu->addAction(deleteObjectAct);
    editMenu->addSeparator();
}

void Window::updateActions(){
    QTreeWidgetItem *rootItem = tree->invisibleRootItem();
    double count = rootItem->childCount();
    bool enable = (count > 0);
//    octreeToolBar->setDisabled(!enable);

    bool octreePushed = octreePushButton->isChecked();
    if(!enable && octreePushed) octreePushButton->setChecked(enable);
//    saveOctreesAct->setEnabled(octreePushed);

//        octreePushButton->setChecked(true);
//        openObjectsAct->setEnabled(false);
//        saveObjectsAct->setEnabled(false);
//        saveObjectsAsAct->setEnabled(false);
//        saveOctreesAct->setEnabled(false);
//        octreeToolBar->setDisabled(true);
//        operationToolBar->setDisabled(true);
//        objectsToolBar->setDisabled(true);

//    octreePushButton->setChecked(staticOctree);
    openObjectsAct->setEnabled(!staticOctree);
    saveObjectsAct->setEnabled(!staticOctree);
    saveObjectsAsAct->setEnabled(!staticOctree);
    if(!staticOctree){
        saveOctreesAct->setEnabled(octreePushed);
        octreeToolBar->setDisabled(!enable);
        operationToolBar->setDisabled(previousSelected.size()<2);
    }
    else{
        saveOctreesAct->setEnabled(false);
        octreeToolBar->setDisabled(true);
        operationToolBar->setDisabled(true);
    }
    objectsToolBar->setDisabled(staticOctree);

    analysisObjectAct->setEnabled(count == 1);
    deleteObjectAct->setEnabled(enable);
}
